package com.castle.fortress.admin.contract.info.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.contract.info.entity.ContractEntity;
import com.castle.fortress.admin.contract.info.dto.ContractDto;
import com.castle.fortress.admin.contract.info.service.ContractService;
import com.castle.fortress.admin.contract.review.entity.ContractReviewEntity;
import com.castle.fortress.admin.contract.review.service.ContractReviewService;
import com.castle.fortress.admin.contract.review.dto.ContractReviewDto;
import com.castle.fortress.admin.contract.enums.StanceEnum;
import com.castle.fortress.admin.contract.enums.IntensityEnum;
import com.castle.fortress.admin.contract.enums.ReviewMethodEnum;
import com.castle.fortress.admin.contract.enums.ReviewStatusEnum;
import com.castle.fortress.common.utils.ConvertUtil;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.enums.OperationTypeEnum;
import com.castle.fortress.admin.core.annotation.CastleLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import springfox.documentation.annotations.ApiIgnore;
import org.apache.logging.log4j.util.Strings;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import com.castle.fortress.admin.utils.ExcelUtils;
import javax.servlet.http.HttpServletResponse;
import com.castle.fortress.common.entity.DynamicExcelEntity;

import java.util.*;

/**
 * 合同信息表 控制器
 *
 * @author
 * @since 2025-04-23
 */
@Api(tags="合同信息表管理控制器")
@Controller
public class ContractController {
    @Autowired
    private ContractService contractService;

    @Autowired
    private ContractReviewService contractReviewService;

    /**
     * 合同信息表的分页展示
     * @param contractDto 合同信息表实体类
     * @param current 当前页
     * @param size  每页记录数
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.QUERY)
    @ApiOperation("合同信息表分页展示")
    @GetMapping("/contract/info/contract/page")
    @ResponseBody
    public RespBody<IPage<ContractDto>> pageContract(ContractDto contractDto, @RequestParam(required = false) Integer current, @RequestParam(required = false)Integer size){
        Integer pageIndex= current==null? GlobalConstants.DEFAULT_PAGE_INDEX:current;
        Integer pageSize= size==null? GlobalConstants.DEFAULT_PAGE_SIZE:size;
        Page<ContractDto> page = new Page(pageIndex, pageSize);
        
        // 使用自定义SQL查询而不是之前的方法
        IPage<ContractDto> pages = contractService.pageContractWithSql(page, contractDto);

        return RespBody.data(pages);
    }

    /**
     * 合同信息表的列表展示
     * @param contractDto 合同信息表实体类
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.QUERY)
    @ApiOperation("合同信息表列表展示")
    @GetMapping("/contract/info/contract/list")
    @ResponseBody
    public RespBody<List<ContractDto>> listContract(ContractDto contractDto){
        List<ContractDto> list = contractService.listContract(contractDto);
        return RespBody.data(list);
    }

    /**
     * 合同信息表保存
     * @param contractDto 合同信息表实体类
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.INSERT)
    @ApiOperation("合同信息表保存")
    @PostMapping("/contract/info/contract/save")
    @ResponseBody
    public RespBody<String> saveContract(@RequestBody ContractDto contractDto){
        if(contractDto == null ){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ContractEntity contractEntity = ConvertUtil.transformObj(contractDto,ContractEntity.class);
        if(contractService.save(contractEntity)){
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 合同信息表编辑
     * @param contractDto 合同信息表实体类
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.UPDATE)
    @ApiOperation("合同信息表编辑")
    @PostMapping("/contract/info/contract/edit")
    @ResponseBody
    public RespBody<String> updateContract(@RequestBody ContractDto contractDto){
        if(contractDto == null || contractDto.getContractId() == null || contractDto.getContractId().equals(0L)){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ContractEntity contractEntity = ConvertUtil.transformObj(contractDto,ContractEntity.class);
        if(contractService.updateById(contractEntity)){
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 合同信息表删除
     * @param id
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.DELETE)
    @ApiOperation("合同信息表删除")
    @PostMapping("/contract/info/contract/delete")
    @ResponseBody
    public RespBody<String> deleteContract(@RequestParam Long id){
        if(id == null ){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if(contractService.removeById(id)) {
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 合同信息表批量删除
     * @param ids
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.DELETE)
    @ApiOperation("合同信息表批量删除")
    @PostMapping("/contract/info/contract/deleteBatch")
    @ResponseBody
    public RespBody<String> deleteContractBatch(@RequestBody List<Long> ids){
        if(ids == null || ids.size()<1){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if(contractService.removeByIds(ids)) {
            return RespBody.data("保存成功");
        }else{
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 合同信息表详情
     * @param id 合同信息表id
     * @return
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.QUERY)
    @ApiOperation("合同信息表详情")
    @GetMapping("/contract/info/contract/info")
    @ResponseBody
    public RespBody<ContractDto> infoContract(@RequestParam Long id){
        if(id == null){
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        ContractEntity contractEntity = contractService.getById(id);
        ContractDto contractDto = ConvertUtil.transformObj(contractEntity,ContractDto.class);

        return RespBody.data(contractDto);
    }

	/**
     * 动态表头导出 依据展示的字段导出对应报表
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.EXPORT)
	@PostMapping("/contract/info/contract/exportDynamic")
	@ApiOperation("动态表头导出，依据展示的字段导出对应报表")
	public void exportDynamic(@RequestBody DynamicExcelEntity<ContractDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
		List<ContractDto> list = contractService.listContract(dynamicExcelEntity.getDto());
		//字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
		List<List<Object>> dataList = null;
		/**
        * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
        */
		ExcelUtils.exportDynamic(response,dynamicExcelEntity.getFileName()+".xlsx",null,list,dynamicExcelEntity.getHeaderList(),dataList);
	}

    /**
     * 合同信息和审核记录的保存/更新
     * 如果 contractDto.contractId 有值，则更新现有记录
     * 如果 contractDto.contractId 为空，则创建新记录
     * 
     * @param contractDto 合同信息和审核参数
     * @return 包含合同ID的响应
     */
    @CastleLog(operLocation="合同信息和审核记录",operType = OperationTypeEnum.INSERT)
    @ApiOperation("合同信息和审核记录保存/更新")
    @PostMapping("/contract/info/contract/saveWithReview")
    @ResponseBody
    public RespBody<Object> saveContractAndReview(@RequestBody ContractDto contractDto) {
        try {
            // 验证参数
            if(contractDto == null) {
                throw new BizException(GlobalRespCode.PARAM_MISSED);
            }
            
            // 验证审查立场是否有效
            if (contractDto.getStance() == null || StanceEnum.getByCode(contractDto.getStance()) == null) {
                return RespBody.fail("审查立场参数无效，可选值：" + 
                        Arrays.toString(Arrays.stream(StanceEnum.values()).map(StanceEnum::getCode).toArray()));
            }
            
            // 验证审查尺度是否有效
            if (contractDto.getIntensity() == null || IntensityEnum.getByCode(contractDto.getIntensity()) == null) {
                return RespBody.fail("审查尺度参数无效，可选值：" + 
                        Arrays.toString(Arrays.stream(IntensityEnum.values()).map(IntensityEnum::getCode).toArray()));
            }
            
            // 验证审查方式是否有效
            if (contractDto.getReviewMethod() == null || ReviewMethodEnum.getByCode(contractDto.getReviewMethod()) == null) {
                return RespBody.fail("审查方式参数无效，可选值：" + 
                        Arrays.toString(Arrays.stream(ReviewMethodEnum.values()).map(ReviewMethodEnum::getCode).toArray()));
            }
            
            // 调用服务层保存/更新合同和审核记录
            Long contractId = contractService.saveContractAndReview(
                    contractDto, 
                    contractDto.getStance(), 
                    contractDto.getIntensity(), 
                    contractDto.getRuleListId(), 
                    contractDto.getReviewMethod()
            );
            
            if(contractId != null){
                Map<String, Object> map = new HashMap<>();
                map.put("contractId", contractId);
                // 返回成功信息和合同ID
                return RespBody.data(map, "保存成功");
            }else{
                return RespBody.fail("操作失败，请检查输入参数或联系系统管理员");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return RespBody.fail("系统异常: " + e.getMessage());
        }
    }

    /**
     * 获取合同和审核记录的详情
     * 
     * @param contractId 合同ID
     * @return 包含合同信息和审核记录的详情
     */
    @CastleLog(operLocation="合同信息和审核记录",operType = OperationTypeEnum.QUERY)
    @ApiOperation("获取合同和审核记录详情")
    @GetMapping("/contract/info/contract/detailWithReview")
    @ResponseBody
    public RespBody<Object> getContractAndReviewDetail(@RequestParam Long contractId) {
        try {
            // 验证参数
            if(contractId == null) {
                throw new BizException(GlobalRespCode.PARAM_MISSED);
            }
            
            // 调用服务层获取详情
            ContractDto contractDto = contractService.getContractAndReviewDetail(contractId);
            
            if(contractDto != null){
                return RespBody.data(contractDto);
            } else {
                return RespBody.fail("未找到合同信息");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return RespBody.fail("系统异常: " + e.getMessage());
        }
    }
    
    /**
     * 级联删除合同及关联数据
     * 删除合同表数据的同时，级联删除与之关联的审核记录和规则关联数据
     * 
     * @param contractId 合同ID
     * @return 操作结果
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.DELETE)
    @ApiOperation("级联删除合同及相关数据")
    @PostMapping("/contract/info/contract/cascadeDelete")
    @ResponseBody
    public RespBody<String> cascadeDeleteContract(@RequestParam Long contractId) {
        try {
            // 验证参数
            if(contractId == null) {
                throw new BizException(GlobalRespCode.PARAM_MISSED);
            }
            
            // 调用服务层级联删除
            boolean success = contractService.cascadeDeleteContract(contractId);
            
            if(success) {
                return RespBody.data("删除成功");
            } else {
                return RespBody.fail("删除失败，请检查合同ID是否正确或联系系统管理员");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return RespBody.fail("系统异常: " + e.getMessage());
        }
    }
    
    /**
     * 批量级联删除合同及关联数据
     * 删除合同表数据的同时，级联删除与之关联的审核记录和规则关联数据
     * 
     * @param contractIds 合同ID列表
     * @return 操作结果
     */
    @CastleLog(operLocation="合同信息表",operType = OperationTypeEnum.DELETE)
    @ApiOperation("批量级联删除合同及相关数据")
    @PostMapping("/contract/info/contract/cascadeDeleteBatch")
    @ResponseBody
    public RespBody<String> cascadeDeleteContractBatch(@RequestBody List<Long> contractIds) {
        try {
            // 验证参数
            if(contractIds == null || contractIds.isEmpty()) {
                throw new BizException(GlobalRespCode.PARAM_MISSED);
            }
            
            // 批量级联删除
            boolean allSuccess = true;
            for (Long contractId : contractIds) {
                boolean success = contractService.cascadeDeleteContract(contractId);
                if (!success) {
                    allSuccess = false;
                }
            }
            
            if(allSuccess) {
                return RespBody.data("批量删除成功");
            } else {
                return RespBody.fail("部分或全部删除失败，请检查合同ID是否正确或联系系统管理员");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return RespBody.fail("系统异常: " + e.getMessage());
        }
    }
}
